{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "%matplotlib inline\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "import bayesnet as bn\n",
    "\n",
    "np.random.seed(1234)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "x_train = np.linspace(-3, 3, 10)[:, None]\n",
    "y_train = np.cos(x_train) + np.random.normal(0, 0.1, size=x_train.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "class NeuralNetwork(bn.Network):\n",
    "    \n",
    "    def __init__(self, n_input, n_hidden, n_output):\n",
    "        super().__init__(\n",
    "            w1=np.random.randn(n_input, n_hidden),\n",
    "            b1=np.zeros(n_hidden),\n",
    "            w2=np.random.randn(n_hidden, n_output),\n",
    "            b2=np.zeros(n_output)\n",
    "        )\n",
    "\n",
    "    def __call__(self, x, y=None):\n",
    "        h = bn.tanh(x @ self.w1 + self.b1)\n",
    "        mu = h @ self.w2 + self.b2\n",
    "        self.py = bn.random.Gaussian(mu, 0.1, data=y)\n",
    "        return mu.value"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "model = NeuralNetwork(1, 20, 1)\n",
    "optimizer = bn.optimizer.Adam(model, 0.1)\n",
    "optimizer.set_decay(0.9, 100)\n",
    "\n",
    "for _ in range(10000):\n",
    "    model.clear()\n",
    "    model(x_train, y_train)\n",
    "    log_likelihood = model.log_pdf()\n",
    "    log_likelihood.backward()\n",
    "    optimizer.update()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "image/png": "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\nrkJggg==\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x10ab474e0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "x = np.linspace(-3, 3, 1000)[:, None]\n",
    "plt.scatter(x_train, y_train)\n",
    "plt.plot(x, model(x), c=\"r\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "class RegularizedNetwork(bn.Network):\n",
    "    \n",
    "    def __init__(self, n_input, n_hidden, n_output):\n",
    "        super().__init__(\n",
    "            w1=np.random.randn(n_input, n_hidden),\n",
    "            b1=np.zeros(n_hidden),\n",
    "            w2=np.random.randn(n_hidden, n_output),\n",
    "            b2=np.zeros(n_output)\n",
    "        )\n",
    "\n",
    "    def __call__(self, x, y=None):\n",
    "        self.pw1 = bn.random.Gaussian(0, 1, data=self.w1)\n",
    "        self.pb1 = bn.random.Gaussian(0, 1, data=self.b1)\n",
    "        self.pw2 = bn.random.Gaussian(0, 1, data=self.w2)\n",
    "        self.pb2 = bn.random.Gaussian(0, 1, data=self.b2)\n",
    "        h = bn.tanh(x @ self.w1 + self.b1)\n",
    "        mu = h @ self.w2 + self.b2\n",
    "        self.py = bn.random.Gaussian(mu, 0.1, data=y)\n",
    "        return mu.value"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "model = RegularizedNetwork(1, 20, 1)\n",
    "optimizer = bn.optimizer.Adam(model, 0.1)\n",
    "optimizer.set_decay(0.9, 100)\n",
    "\n",
    "for _ in range(10000):\n",
    "    model.clear()\n",
    "    model(x_train, y_train)\n",
    "    log_posterior = model.log_pdf()\n",
    "    log_posterior.backward()\n",
    "    optimizer.update()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x10ac31c18>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "x = np.linspace(-3, 3, 1000)[:, None]\n",
    "plt.scatter(x_train, y_train)\n",
    "plt.plot(x, model(x), c=\"r\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "class BayesianNetwork(bn.Network):\n",
    "    \n",
    "    def __init__(self, n_input, n_hidden, n_output):\n",
    "        super().__init__(\n",
    "            w1_mu=np.zeros((n_input, n_hidden)),\n",
    "            w1_s=np.zeros((n_input, n_hidden)),\n",
    "            b1_mu=np.zeros(n_hidden),\n",
    "            b1_s=np.zeros(n_hidden),\n",
    "            w2_mu=np.zeros((n_hidden, n_output)),\n",
    "            w2_s=np.zeros((n_hidden, n_output)),\n",
    "            b2_mu=np.zeros(n_output),\n",
    "            b2_s=np.zeros(n_output)\n",
    "        )\n",
    "\n",
    "    def __call__(self, x, y=None):\n",
    "        self.qw1 = bn.random.Gaussian(\n",
    "            self.w1_mu, bn.softplus(self.w1_s),\n",
    "            p=bn.random.Gaussian(0, 1)\n",
    "        )\n",
    "        self.qb1 = bn.random.Gaussian(\n",
    "            self.b1_mu, bn.softplus(self.b1_s),\n",
    "            p=bn.random.Gaussian(0, 1)\n",
    "        )\n",
    "        self.qw2 = bn.random.Gaussian(\n",
    "            self.w2_mu, bn.softplus(self.w2_s),\n",
    "            p=bn.random.Gaussian(0, 1)\n",
    "        )\n",
    "        self.qb2 = bn.random.Gaussian(\n",
    "            self.b2_mu, bn.softplus(self.b2_s),\n",
    "            p=bn.random.Gaussian(0, 1)\n",
    "        )\n",
    "        h = bn.tanh(x @ self.qw1.draw() + self.qb1.draw())\n",
    "        mu = h @ self.qw2.draw() + self.qb2.draw()\n",
    "        self.py = bn.random.Gaussian(mu, 0.1, data=y)\n",
    "        if y is None:\n",
    "            return self.py.draw().value"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "model = BayesianNetwork(1, 20, 1)\n",
    "optimizer = bn.optimizer.Adam(model, 0.1)\n",
    "optimizer.set_decay(0.9, 100)\n",
    "\n",
    "for _ in range(10000):\n",
    "    model.clear()\n",
    "    model(x_train, y_train)\n",
    "    elbo = model.elbo()\n",
    "    elbo.backward()\n",
    "    optimizer.update()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYAAAAD8CAYAAAB+UHOxAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJztvXmcY1WZ//85N3sqqb2qu6v3jV5YuykaGhFoQTYXcMYF\ndRBHHUbnx4w6P3EddRzR0ZFxHMVlcIevI+6KXxEQbECgG7obaOiV3vfu2pdU9tzz/eNz06mqzk1S\nValKKnner1deuffm5NyTquQ85zyr0lpDEARBqD6MUg9AEARBKA0iAARBEKoUEQCCIAhViggAQRCE\nKkUEgCAIQpUiAkAQBKFKEQEgCIJQpYgAEARBqFJEAAiCIFQpzlIPIBfNzc16wYIFpR6GIAjCtGHL\nli1dWuuWQtqWtQBYsGABNm/eXOphCIIgTBuUUocKbSsqIEEQhCpFBIAgCEKVIgJAEAShShEBIAiC\nUKWIABAEQahSRAAIgiBUKSIABEEQqhQRAIIgCFWKCABBKBRtAkOHgeSQfZtUbOrGIwgTpKwjgQWh\nbEgMAn3bKAQAwFkDaA1EOwBvCwAFpKJA/zbAOwtw+gBPU+b9Q0d47vSXZPiCkA0RAEJ1o00gFeGE\nPpzkEK/1bgVcQSDWA8S6AIefk370FFC7AhjYCYT2A646oGYedwBDBwCHD3AGAZjA4D4g3gdAA855\npfiUgpAVEQBC9ZIcAvp3AMkQ4AwA/jmcrJUDMONcrSfDQLwXSIW5wk+FAcPB9yQG+Zrh5vV4N98X\n76Gg6HoGMDxArJN9Rt0UHIHFgKcRCJ8ADBfgbS71X0KoUkQACNVFKg4M7gGU4qo9FePqXpu8HjkB\nQFlCoBYwY2yTigJ1ywEzCQzu5a5AmxQcyRAQt9o5/LxmJjN9aZNCYygKODyAMoDIcSBykkLGcPGa\nK1jqv45QZYgAECoTrYFEH1fg0Q7AcALeGUBigOqYZD/gaqD6JxXlSh4AAosAaK7uo6f4HldtRkVk\nOCkIRtDM9g4f+3fXUYAMJ97PyT60H7QXRADl4s5hYBcFhrsB8M3kvRwefgalJvkPJVQzIgCEyiR8\nHBjYwcnbTPJa6CAn1ngPJ2o4qOJx13Nydni5Egd4zV1f+P3Sq3dPY/bX3XV89s6w1ECLADMBxLop\noJQBQFON5GkFPA3AwB6gqZ3ta8R2IBQfEQBCZZK0VvCmpZZJDAIKgJmiyiW4hJ45Ti/gaebKfipw\n12P9/jju2/AiOkMxLK8L4a0XNOCiRS2ATgHQVFMNHQCSEUtVdArwtU3dGIWqQeIAhMohEeJqPxUF\noicB/2zq3xODnDyTYa7Q/dZkGlwI+GZN6cS6flcH7l6/Fx2hGDSAXf1+3PV0DM8d6Ob4kmEg0csd\nisMDhA5QTdS3nZ9PEIpIUQSAUuoHSqkOpdQ2m9eVUurrSqm9SqmXlFKri3FfQYA2ge5NNOT2bqGO\nfegQV84OP3XqrhqqXoKLS25ovW/DIcSS5ulzDQNDSQP3bE4BwUVAYAHgnckVv6eJgiw5SNVQzybu\nWpKR0n0AoaIo1tLnRwDuBnCvzevXA1hqPS4G8G3rWRAmRjLM1fLgHurSNeiK6ZudWdm7G6zGDrte\npozOUPZI4VOhJA3HyjFyWeZrA8LH+Ll0nLaCgVeApgtpQ3DXU6UlCOOgKDsArfWTAHpyNLkRwL2a\nbARQr5SaVYx7C1VMvJcr/lg3XTHNJFfM2izbiNuWgGdM1+EKArVnAUhxRxM+xs8Y72MMQ2KANgNB\nGAdTZQOYDeDIsPOj1jVBGB+pKND7Elf97joafJ1+est4mzPePFNJx1+A/p05m9yydj48zpFj8zgN\n3LJ2vv2blAHUzKc6q3YZbRvhY3RzHdwH9L7A3YAgjJGycytQSt0G4DYAmDdPXN+ELKTiQPcWToCp\nKBBYSE+eySLeB+z4MlVLc94ENF9Mw/Kh+4HuZ4HG1cCyDwLPf5jtr9ts29W65a0AaAvoDMXQEvDg\nlrXzT18vCGcNk9IBQKyDaqPBvYB/LuAKjPdTClXIVAmAYwDmDjufY107A631PQDuAYD29nY9+UMT\npg2pOCe8/p2W6iPKiX900FUxiJwEIseAfd8HQvuoZgKAjifObNu/fWQuoYfagbbXAef+K7Drq8Ch\nn/L6xd8H+rdh3bJ3jG3CH40yaCxOjzMVpUCIdQLNa8UmIBTMVAmABwDcrpS6HzT+9mutT0zRvYVK\nIBXnJBfaB5hRum86bPTmhTK4D9AJ4NTjADRw+JdAon98fe35zsjz43/gYzjPvpfPwWX08492Amf9\nw/jul8Y3EwgfpTFcJ4GuDQwy87RM/O8jVDxFEQBKqZ8CuBJAs1LqKIDPAnABgNb6OwAeBHADgL0A\nwgD+thj3FaqAxADQtwNMz9BPNYy7YeKTm9bA028rvH3NAmDoYGFtfW10Q7Vj0/szx8kQMPuNNPSO\n127hDFBNlYqxP+VkHqLa5SV3exXKG6V1+WpZ2tvb9ebN9vpUoYIZ3M/VeaybaZhTURp7J6rrj5wE\nnni9/esLbwWO/19g5ceZLbThAuDUemDOTUD4MLDra8CKO2iIheLDcHECfv5DwNmfAOrOZl9mkq6o\nvS8CJx5h8rl9381+37bXA8s/NLb0E6PRVioJDaa1qF0O+GaMvz9hWqKU2qK1bi+orQgAoaxI5+3p\n2kA3TzMJwKShdywc/hWNtcoBbHwvbQfz3gIc/oX9e867E2i7btxDz4s2ge3/Dsy5kQbkEw+d2WbG\nOq7ohw4Ba+4Ze5RyMgKEjzBFtW82BUHDeaXxihJKgggAYfoysAeInuDEnwwD/nGEi0ROAE+8gcee\nZu4ghjP62jXPcMKcalIxoGcLhUHXM2e+3nQJMP+tVCkFl4ytbzPJHYurHqhbwVoHQlUwFgFQdm6g\nQpVipujWCZNGTeWwUjOPg54tmeNRk//L0ZX45J7bcOuMx3HhvBosXHlDaSZ/gHaMlku54s8mALo3\n8gEAF3yJFcj8BYbPGE6WpgwfBrCiaEMWKgvZAQjlQfcmujE6a+nN4gyMPRd+Mgxs/yLQ/RxTPqcJ\nLMLzgQ/gnk1D6I55EdFeAAzAun3dkom5ZBab5BD/FjULgKfefObrOWIMshLroRoIBgVOw/niJlrh\njGUHIIpBobSk4nTHjHUxmjVynF4shU7+0U4aih9qBx69nHr1eA9wzmeAy38HzLoeWP1fuPuFAI5G\n609P/gAQS5q4b8OhSfpg48RZA8y4kn7+l/zozNd3/zdw8s+F9+cKckcV66Iw6N5UpIEKlYCogITS\noTUnJJ1kLnz/nLFXwXr8+uzXZ74WcPqA8z8PAOgMHcjazC45W1lQf86Z1w7cx+e191JNVrssdx+G\ni5lQ02mm055V7gb+rY3SJ8gTSocIAKF0mAkgOcDJPxXltbFM/tGuM6+96n6ryLtvxOWWgAcdWSZ7\n2yRs5cKl/8uEd/XnAE/elLm+4V18vvovZ3zWM3DX8ZEYpOG5fxvgqKFXUvOayRu7UPaICkgoDeET\ndM1Mxan3Hks6h54twO6vA48Pc9lsvQK4ZiO9ZRouOOMt40rCViixLquaFzKCrFjUnkXXVP8c4MoH\ngQu/xjrHaR59NfD02wvryxVkrqDwCdYYMIs8VmHaITsAYepJxZnSwXBZ/uozC/dT79oIbL595LW1\n947M/5+FCSdhS4YYRFazgPeJ93PSNxOMVjbcfAwdolom3jexoK5seFv5uPzXVOOkdwGDe6jn983O\nv4NyeCkk0wVzhKpGBIAw9fS+YJVt7KT6YizBTi/cMfI8sASoW1nQW9ctby1swjeTnNgNF+0ToYOA\nw81dSjLEiT0V4Wfwz2F6ishJei4ZXiB0iLr20wniNACD74+cANy1bDtevDP4uOwXwFNv4bUnb+LO\n57w7KVBzoRRTZ5sp1hv2NIstoEoRASBMLaGDXB3rBFAztzCdf+gg6+Lu/yEnXoAeMtmMpBNBp2gs\nTat0DA93Js4A4PABSNHDKBXJqGFctRQKDjcnVGcNAE3BET3FyFx3LfuFYl/RLsDn5D2GZxEdK4GF\nwBW/B174KDCwkykntnwQuOxn+d/rbqBXUOfTDDRrXCXJ46oQEQDC1BE+BgzsYHFzT1Nhk3/42Jn+\n8Bd/r3iTv9acqON9HI+7nsZRVx3gmwPoGMerwNW9cvI9/jl8n7uRKiAV5CRvuPneeC8N3N6gpXtP\n0NbhaQQGeikEdBJwJ7gaH28wmm8WcOl9wM7/ZNrp0D6mvrjgi9wl5MLTyN1L9BRVSv628Y1BmLaI\nABCmhvBxTk7JIa5cC9H5x7qAFz6SOQ8sAs75NFB/7sTGMriXunwzRgHj8NM4qjXTKLvqeVy3nOPs\n2UKVUM18pqQ240yvkAxTfeJuoPAInwCQ4qQc72e1Mk8D4G6iwTUxSIGRjFLtZcYyUc++tomVsVz2\nj0BwKbDt34C+rcDjrwMu+nb+jKC+mYzDCO3huMcafCdMa0QACJOPmeQEE+vjBFvI5L//R8Ceb2e8\nawCg/Rv5V7V2hI9a0cUGV/GDe2kQdTcAzvQEmQIa2znBJ/oztgn/PKp9fDOpJklaaqimC633Wfrz\nwLAKdj7vqEycvkxx+tZX0R2zbxureEFzBW7GKTQCC2kf8c0o3DvKcANz3gjABLbdyWubPgA0rQEu\n+lbu99bM5y5g6DCFkLelsHsK0x4RAMLkkYpysk0McGLzthZm/Ox8BnjlburZdQpY8VFm8hzL6lSb\nnFAdXsuom6Sh1uHnCt9jGXRdtUDwLE7OZoz3cHgAxzBj8fCJ3N2QmcgngsNDAZKKcicx8ApTObsb\nuSJ319FgPNYkbnNuAmbfCKy/hmqo7uf4t8gldA0n/zcDOygAPK+W7KFVgggAYfLo3cpnTzMn2nyT\nf7wPWH9tZtW/7iFOSOMp+RjrYXK54BKubE/fX1Pd42vjriCwkLpwZQBGCdwiHV4+mtqZxjlykrYB\nbysFQWLAMkCrwr2llAKWfxh46TM8f3gNsPJjFKJ2GC7+naM93I0Ybss2IXmDKhkRAMLkkAzTc8dM\nciVuePO/p/vZzOQ/763jq2Zlxqmvj3XRoDtk5cYPLMykP3BaOn/fzPKZ4AynJYyagNABHicG+IhZ\nnkfK4G6lkJ1Q2w1U7Wy4lec7vsz/SdsN9ioeTxMN3gO7KIRqV0pBmQpHBIAwOfQ8T52/GaXaJVca\n43gfyzOmC6+f/SmqMsaK1kDoMGAYGeNsrJOTfe1ZZ7Yvl8l/OK5aZuwEgIZVNJoP7MbpoP3IscLV\nQunKZGle+QYw+Apw/hfs31MzlwZ7nWQJTBEAFY0o+oTiok2g92VOXP6ZVMHUzLFftQ4dAQ79LDP5\nA5z8x+qNkopZBVACFDiBRUDjhZZXT9P4P08p8TRyQna4AU89P1sqyl2ONgvrY/k/jzw/8TCw73v2\n7ZUBOFzcJcW6aIcQKhbZAQjFpfclTuapKGDkqd97+JfAji/x2D+Xidxi3WOf/E0rw6Xh4YQP0KXR\ncFRGsrN00JkDVOPE++hm6p3BILNcLHgHMOdNwMufYT8nHgL2fIdpsu12ZWlPq2g3PZV846jKJkwL\nZAcgFI/ICRpek/1c9ecjPfkDXKk6PGMPRkp795hxrpDrVnLSd00g1UK5EVjIuANPE72DvK0UdPFu\nCr98OH3Aqq8AK/7/zLWn32aplnLgbaIglxoCFYvsAITiETmV8WPPR7r4OwDMfgPQ+urC76NNesgE\nFzOrpbeVQVaGrzz1+hPFa7mkOgN07fTPBZx1QMRJg7F3BgVDPtwNwKt/Bfzlr4FUFOHn7sDtRz6d\nOzmeGQVivfzfij2g4pAdgFAcYj1c+ftm5Pchj/UAj1ySOV/6/rHda+gIJ7xYF1UiwbOYy6apvbLz\n2SiDgWreViC4iHmEvDOsal9ZaiNko2b+aSOwP3kc4XAPNICOUAx3r9+L9bs6Rrb3NNOQnhi08hkJ\nlYQIAGFimAlODgO7rUCrPMVJ+ncwSCnNa58aW3SvTtFA6azlTsBZQ3dRb2t1BC+l7SPKoLrLGeAk\nnRiiYIz35e9j1rX4/SArqX105r2nL2ctkemqpVpu6BDQ8wI9rYSKoQp+McKk0vMCXQvDR+iemCto\nq3NDJoc9AFz6E6tg+RiIdnKVX7sU8M4CGldX9qo/F04/dz3emRSiDjf9+AvgF53cga2u2Y1rajec\nvp61RKazBoietHZcQ0UZulAeiAAQxo/WDFBKDjEDZr7J/MCPM8cXfy9/PdvT90kB/bu4y9BJ7jK8\nrUDT6uKkZZjOKAOoXwm0XAq4GhlQlgyNtLFkwelrxTv3fx7H4i34pxk/wwwnVUhZS2QqBxPjObyM\nni7E8CxMC0QACOPHjDPaN53aOBeJAaBnM9UV127KWrbRlshJevV4Z1Df37BqYuOuRJSiHcQVZMW1\n8DEKgXTiulHcsnY+oqoO/3r8NgDA9xfeiTZPf+4SmU4fq48N7p+MTyCUABEAwvhJ9NNN0F3Hid2O\n0AHgsdfweNHfFu7nn4oyKlU5mNbB3UR3yGpV+eTD4WEAXFM7hWX4CFfsqTPVOuuWt+L2dUuQ8szB\nxhBrK9y94D+xbn7qjLanSdtbosfFIFwhKF3GRp329na9efPmUg9DGM3QUeqbB/eNKn2YBZ0C/vIW\nRuk6A8BV6wsTAPE+6py9M7mSbWqnIKgk//7JRJvAiUc4+afCdM21c5FNxYAn3wTEOhgsds3Tufsd\n3McgsvrzCnM/FaYUpdQWrXV7IW1lByCMnfBhevPEuu0Li4cOAB1PAYd/xfazrqPRt5DJX5ssveib\nw0nL4eFEI5N/4SiDdQ4cPibDC+VQ2zg8wFn/wGPTqlOQq9/gIhqF8wWSCWWPBIIJY0cZ9A13+Own\n9GffRxURwFXl+XcW3n9ikLuKmrlUNSj5mo6L5kusamZRACqTmTVb5bG211G/f/AnwMZ3Ays+Asy/\nOXu/ykEhnRxkTIencTI/hTCJFGUHoJS6Tim1Wym1Vyn18SyvX6mU6ldKvWg9PlOM+wpTSLyfRUtC\nh7ny97Xl9t9PZtwRd9e/F+/54Sa84RtP4T0/3HRmsNGI+/RZhVGaubuoXcaIX2HsGA5mFnXVctKP\nnGAkcTa1r1LAsg9lznfelTsRXM189hXaD5g57AZCWTNhAaCUcgD4JoDrAawE8Hal1MosTf+itb7A\nevzbRO8rTDHxXj7CR7gqd3jtA6/6tgFQwPx3YP2CB/HJLcvREYrljjgFKGRi3UDNQvr3e5s5MUmd\n2vGjDO7UHD6rGlqQAjZbNlGlgGufA2pX8PyJNwAHf5q9X8MFQPH/1b+z8OykQllRjB3AGgB7tdb7\ntdZxAPcDuLEI/Qrlhhll7dhADlfBaBdVCIYHWPxe3LfhEGLJkZPDGRGnqSijWJWDK8v6cwqvfiXk\nxnDRM8hdzwR9vtlUsdlFDCsDuPi7mfM937bv2xVk8r/IMaqChGlHMQTAbABHhp0fta6N5lKl1EtK\nqT8qpc7O8joAQCl1m1Jqs1Jqc2dnZxGGJ0wYM8FVYyJEY2yuaN999/B54TsBd132yFIMizjVpjX5\nW37szRePPTpYyI23Bag7B6hdzoyi3pmZymvZcHhpAwDoQZSKZm/nrmeq6LhV+EeYdkyVF9DzAOZp\nrc8D8A0Av7VrqLW+R2vdrrVub2mxKV0nTC2R45z8U9HsBkSAQuLRK4Ejv+b5EgYYZY0sTV83kzQ8\nuoIs1K4qMJNnuWA4uLr3NNGlFqCO384NfP7NwOL38vjx19vYDRw01ju9tA9JbMC0oxgC4BiAucPO\n51jXTqO1HtBah6zjBwG4lFJ5qoUIZUOsl0bdVNR+ku7ZkjH8rrrr9OVb1s6Hxznya+ZxGow4jfdx\nFemqZ0oHCfCaGhxeGvDNVO4I7rlWEflEHwW1Hd4Z3CH2vVzccQqTTjEEwCYAS5VSC5VSbgA3A3hg\neAOl1EylaMlTSq2x7tt9Rk9C+RHvt3YAA0BgQXaDrNbAK9/i8ZUPAjOuPP1SOuK0NeCBAtAa8OD2\ndUuwblkLJx/fPCC4FGg4rzqyeZYL9edS+EZP2bfxNgOX/47HB39CJ4BsGC7A8PI7IkwrJmxp01on\nlVK3A3gYLFr3A631dqXU+63XvwPgzQA+oJRKAogAuFmXcwiykCG0jzlgchUD2fFlYGAHj7OkhFi3\nvHVkoRGtGXDkqgUazinygIWCMJyZGsM6ZW/X8c+m2uj4Hyigz/2sTbs25mwKH2N7seNMCyQVhGDP\n0DGg7wUaDe1cMbs3A5usgi6r7hqx+s9K5CSzhzq8QGAxUG/rDyBMNtoEOp+2qrgtsG/X8RTwvBUj\ncNkv7dsO7suol2rPkkytJUJSQQgTJ3QACO1hmme7yT85lJn8my/NP/kDzDtTswBofpVM/qVGGcys\n6gwCg3vtU0i3XsbvAUBBYNfOP4cCIN4ncQHTBBEAwkjMJFf1sV6rwleOrfz66zPH5/5rYf07/dT3\ne5smNEyhSLgCgH8W/89DB+3bvepnfA4fBV78WNYMo3B4KCjiPYwQltiAskcEgDCSVJQ/7mS/VeHL\n5isyuI8+4gBVP4Xkg0lFAWjJ7VNuBM8CPK2cvO1W7t5mZnIFgI4ngD+9KrtrqOHk92boEJMACmWN\nCABhJGac7pzRjtxumZut7JEz1gGtV+TuM3KSFb0iJ2kklijf8sLhYRCew09//vDR7JO7Kwi03505\ntwsQc/qZKyoh5SPLHREAwkiSIT7c9dlX/9FTwEPtzAEDABd8KX+uHjPBEo6+NqDxwuKPWZg4Dq9V\ndKee/6+UTVBX8yWZ476t9v0ZbtqIJFFcWSMCQMgweJBun6move4/HekLABd+PXdaiFgvV5MOP9C0\nBmhZK77+5UztcsDTQqNwrprCrno+b77dPpJYKbqXJmxyDgllgfwaBZIYYFKvaCdXgc4sxVe0CZx8\njMcLbwWa1+buMxVhgFD9SqkcNR1wuOni6QqOSOd9BsPVQP3b7dsZDsYFpOJFG6JQXEQACPyR9u+0\n/PM9FACjOfJb4NgfMp4iy/4xt+pHm+wruISqH2F64AxS+HtnMLPr4L4z29QtB86xSnpsfDdVRtlw\n1QGDu4HeFyZtuMLEEAFQ7WiTq/5UmPlcfLPOVP9EO4DtdwLbPsfzi7+fv99kmEXcg4tF7TOdcPro\npluzgO6cDl/2djOvyhzv+Vb2NoaT0d6SIqJskV9mNRPvo8+/GaPe39+WXac/+gfccH7uflMxCpWa\nubnbCeWLux5wN7KuQ7bU0c4aOgAAwIH77D2CPM30LOt7OXvsgFBSRABUNZor/+QQJ/lsmT51Cnh6\nWG3Y4frfM9qamb4CCyUVwHTG4aEAdwVYQCYbM68GGq2MA0/b1A8GuNAY2GtfhEYoGSIAqpnQfkv1\n08+8PNn8/gdeGXk+3A1wNOn4gVSUemJD8vtPa+pWAvXnUcdvp+dPR4CHj9JmkI3aZTQIDx209xoS\nSoIIgGpFayAZ4erO4bY36O4bpu8/7848faa45fe22uuOhemFKwAEl3ORkA3fTODC/+bxzv/I3kYp\nqpJiXUDP85MzTmFcSEhmtWLGMq5+XptUz30vAx2P8/i6ArKymimgdglTCIvht3LwNgH9MS4YnFkE\ne/OlFPyn/kzbjzdLJT9PE1VAsS6qCuX7URbIf6FaMeP01HH47Ff/keN8risgZ39yiELFXSeqn0rD\nGWAwX7Qzu0FYKWYVBYAnb7QpH6kATwNVjpEcRWiEKUUEQDViJrmld/q5Ws9GvB/Y+ikeX2Tj5ne6\nvwR1/742wFFT3LEKpUcpGvSdfiBkk+At7QVkxoFjD2RvA9AtNHqSqUTsbAbClCECoBoJHQBCe+1f\nN+PA5v+Px/Nvti8ED3A7n64CVbeC9gSh8mi6kMXflYOJ/Uav8odXgtv2eS4IsuGqBYYOA71bmXZE\nKCkiAKqJZATo3gLEOrgNz5bvJ9YNbP0XYGAXDXcrPmLfnzZpRK6ZzyRvTln9VzSGj7EiDi8wsJsL\nhTTLPwyc+7mMo8DjN1DfPxplsLxovH/k+4WSIAKgmkgOAakQC3UElzDny2jWX0tjHgCs/XHu/oYO\ncjvvbubKTqhsGs6nms/dQNtRYli+IKcfmP06oO06AJZNqdvGccBwATAZGGYXQCZMCSIAqoXEIDD4\nClf+3ubsht/RBr7gEvv+zCR3AO56wCOJ3qoChycjAJxee+eBqx/n8+Bu+778cwAzCnRvKvowhcIR\nAVAt9G7N6GUNGz39cO+Mtffl7i/Rx7TAnpZMemCh8jEcDOzKFefhrAFqVwJdG+3TShtOq/JchDvS\nZGRyxivkRARANWCm6PPvCtr7/KeiwMuf5fG8t9Kga4dOAckoV/+1y/IXhBEqDMU038kcFb8W/g0w\nuId5guwwE4BOsF3kWPGHKeRFBEA1kLJ+qO56RnZm4+hvM2l7F/1t7v4G99Hfv2mN6P6rEYeX3l6G\nx75uwKxrWGt4zzeBk49mb+NtBjTso4yFSUcEQKWjNXP95/O4OPo7/rDP+7fskZxpzCRVSO4mWflX\nK0oxR1DdypGG4NEseCefX/x49tfdDRQCyQGqH+3yDQmThgiASicVsQq859DZ9r7IbXjrOqDthtz9\nxbr5o61dWtxxCtMLw8V00cph78kz8+rM8cH/tenHyffHOmmnyiVQhKIjAqDSSQ7xx+ppzP565CTw\n7Pt4vPTvc/QTZsCXTgLBZfY1g4XqwRUA6s+3L/ji8ABz/5rHu75qn1Y6uJQeZamYxAZMMSIAKhUz\nCfRsZc1Wu0Ich34O7P0fHs97G13z7Igc44/TFWTUryAAXFho094WsPQDmeOBXdnbGM5hdYglXfRU\nItlAK5XwYSB6Cs+9sg/f3ZLCydBBtAQ8uGXtfKxb3kqhMDx978o77PtKRpgQTDlp2JNkb0Iah4e1\nJEL7ADjOzBbqrgfWPcwAw83/CFy1PntGUacfGDoCDO7lrrT+7CkZfrUjO4BKJRXDplf24KvPRHAi\nlIIG0BGK4e71e7F+VwcjeAvFjDHa19sqq3/hTGqXUS0Y68z+uqfJKi2ZBJ56c/Y2Di8QmM+61PEu\nKRwzRYhm01K5AAAgAElEQVQAqDSSYYbgx3vxw+cTCCVG1viNJU3ct+EQ8My7Mhfbv2nfn5mgYS64\nCGhcLbp/4UyUYn4fh9deh3/x9/gczZEK2nBzl5mMAX3bij9O4QyKIgCUUtcppXYrpfYqpc7w+VLk\n69brLymlVhfjvsIotAbivTT8xjpxdDD7KqozFMvEBqz+L6D5Yvs+w0fp8y3+/kIuXEEKgNDB7K/X\nrQBaLuPx0BH7fjxNQKKXaSKESWfCAkAp5QDwTQDXA1gJ4O1KqZWjml0PYKn1uA3Atyd6XyELsW6m\neU4MAA4/mgPZXT+X1VqTv68NaF6bp1MFOGu5hReEnBjU+dulf1jwN3w+9VjubnyzRQU0RRRjB7AG\nwF6t9X6tdRzA/QBuHNXmRgD3arIRQL1SalYR7i0A/LEkBuhFkQidTvtwy9r58DhH/ot9TuALbXfx\nZPV/0gMjV7+Gm54eEvQl5EMZgKvBvhZAUzufX7kb2PAue/dRwwEkB4EhSQ8x2RRDAMwGMHxPd9S6\nNtY2wniJdVNnGjnOH5VvFmC4sG55K25ftwStAQ8UgMsaD+OLF+6AJ9ULBBbReyMX0VMUEHZVwwRh\nOMoJuGu5aAjbTN7LPsjn/h3Ak39l04+LasyhA5IkbpIpOzdQpdRtoJoI8+bNK/Fopgk6yZV/KgwE\nFozI9rlueSvdPrUGHv4Q0ANGBb/qfvvC3Glbgk4CDe2AM0vdAEEYjeGhu7CrltliU9EznQYW3sLv\n0/Y72SYbSjFoLBUBIjNzpyUXJkQxdgDHAMwddj7HujbWNgAArfU9Wut2rXV7S0uOnDTCMDRXTO56\n+1TPw8vvmQn7yR+g4VengMASrv5F/SMUQuMqwD+X1eHcjfY1f+vPyRwP2pQmrVvONOORE5IjaBIp\nhgDYBGCpUmqhUsoN4GYAo6tCPwDgXZY30CUA+rXWJ4pwbyEV4+rfjNhP/gDw9M2Z44W32LdL/9ic\nQQnGEcaGUnw43EDtcgYMZnMLHb6if/pme4OvwwvEe+jWLEbhSWHCAkBrnQRwO4CHAewE8HOt9Xal\n1PuVUu+3mj0IYD+AvQC+C+AfJnpfwaL3RSC0h0FaDhtPnROPZI7P+fTI8PzRJIfYl2y7hYngDFAA\n2Ll8nvuvmeOeLdnbuAKsOxEdY+CiUDBKl7FkbW9v15s329QVrXYip+id07WRqyx3jqpcD1neF43t\nwEXfslf/pGI0IjdcAPhmFn/MQnUR6wG6n7VXTR7/I/DSp3n8mj8xPfRodIpCxNsCtF4+ueOtEJRS\nW7TW7YW0lUjg6crQQaB7C70kshV3T5NO0uWdAay+K7/uPxVjXhZBmCieRsDTCgzuz/76rGszx71b\ns7dRDqBmLo3CdvEFwrgRATAd0ZqRkol+Rk0qh33bZ2/j88pPcFtu26cJuOroQpqrnSCMBf9s7gCy\nZaRVBrDCSkL4wkfsJ3jlAKCAgRxF5oVxIQJgOhI9CaTi1Nfn0tUnQsDgKzwe7nmRDTPOib95Te5d\ngiCMBd9MLizCR7IbhIcXIHrkEvt+PE30CEqEWONaKAryS5+ODO6hrj5f8Yx0rv/V/5XbRmAmaVMQ\nb09hMvDPAzzNTFQ4GlcQuORHmXO7+sCGk3EBPZsY8CgUBREA041UHEglGGzjb7Nvt+PLwKGfstpS\n44V5+owA3iagLs8uQRDGQ81coO5s7lhHOZ2s39WB9/wmjKEUA8Z6n/ln+yjiVBgIH6f9q4ydV6YT\nIgCmGwM76fPvrgecNdnbRE4Ch3/B45WfyG/UjZ4ClBtw1xV3rIIAMDbAVQtAMd+/xfpdHbh7/V50\nhOL4mwOfBwA0RLeiY/N/ZO+nZgFQexYdG1JZdhPCmBEBMF1Ixej1EznGrXQuPX1a77/gnUDDefbt\nzCQwdIi6f/H7FyYTw8UFRiwjAO7bcAixpAkASGgX/vsUgxVbw09nTyttOK3vvQKi3XRcECaECIDp\nQmKQKx8zx5feTDKo5vl/5vmiv83dZ7yXW2l3g1T6EiYX5eSO1VV3euLuDI30DPrTwCVIaWtKeuXr\n9n05fcDANmDglckabdUgAmC6ELOiIZ1eIGiTxfPRK4Dn/p7Hq7+a2/ALMMjG08yttXj+CJOJUkDD\nKgoBS33TEjgzcn1bxPpu26WKBrhjdday9kWsZzJGWzXIr77cMZNM9Tx0hBN1tmhJwIoNsFZUypE/\najJhBYg5axgkJgiTjTJYP9jyBspWr+Jrne/mQe+LQMeT9n05fexnYNckDbY6EAFQ7sS6GKEb785d\nvGV4rdUr/pC/38QAPYSa2lmAQxCmAncjFzWp2Bn1KloDHrzrilWZtjvvyt2XpynzmxB7wLgou3oA\nwjCGjgBDh1kdKZc6J3QQOPpbHq/6CuBtzt2vGadXhhh+hanG4WGywfBRoGZupl7FcI7W0GU0cpzP\ndt5uTj/dorue5e6i6aLJH3+FITuAciZ8xFr5e2g8y4aZBJ56M3Dw/7Do9ox19v1pTWNyvI/BOaL3\nF0pB0xqqMyM2GeEv+XHm+Mhv7PtRTisdyiAFgTBmZAYoV4aOWjp9zXwqoysrpRn+I1ryd7n7TIX5\n0Ckp8yiUDqUYAWya/C6OJrAAePWvebz7a7QHZO3HYNUx03oIY0YEQDliJoHB3cyD7puVu92Of8+c\n1+Up4JIMscqS4WXRDkEoFf7ZVAUN7steRH749/7Z93Giz4ZOWmnMB+2zjgq2iAAoJ9KGrHgfv9TB\nJbkzfR66H+h+jsfXbsrdt5lkCgnltN9NCMJU4ayhzt4/L3uOIMPFHFZp+l7K3o+70XpuoEeQXS4h\nISsiAMqJni30ax7Ymbu8I8AV0eGf87h5bf66vdGTjMT0tthXDhOEqcThBgLz7Rckra8Grvwjjzue\nyt7G00iVkSvAxZIkihsTIgDKiVSEmT6jHYDHxt8/zf4f88vumw2s/s/cbc0EdwAOHxBYyMpgglAO\nOHzc+dpltvW2ADNfCxz9df6gL2cNfzuDB4o/zgpFBEA5oDV1ockIhUC+CN699wD7vsvjVf+Rf7dg\nxqxUD9YuId9uQRCmClcdq4alAxOzsfi93PGe+nPuvgwXXaaHRAAUigiAciAxQLVPcpBePfkqd+29\nh8dz3sTIylwkI0yh658L1J9bvDELQjEwnFThmHF7IRBYTFvBji8Bm//JfrdgOGkDMBNAz/OTNuRK\nQgRAOZAKcxfgncl0t7kiftN6f4DqnHwkh4CahYCvjeHzglBueFtYiyLRn70spFLAfGYKRdczuVNE\n1C1nksN47+SMtcIQAVBqho4AvS8D7tr8E7SZHBkeP+dNudvrFHcMDefK5C+UL8oAauZRCMT7sreZ\n+1e0BQBA/47c/dUutXYUg8UdZwUiAqCUJIeYjx+pwgqxn3w0c3zd5vyTeqyH22u7UHpBKBeUouND\nMszypKMxnMAF/86MogfutY8iTmPGmURRyIkIgFKRigO9LzEniqs2f/vBvcBuK0f6vLflb58cknw/\nwvTCGbTKnOYo9zjzKj4/8YbcfSXDgI5bz1I+0g4RAKUgFQV6X2COf39b/sAsMwk8fTPbr/gIsPKO\nPP3HqFryzaZnhCBMBwwn8wQpp31Ub9sNmeNn3mXfl38ujcqn1gPhw/aqpSpHBEAp6N0KxHuooy9E\nPbP/B5njpktyt02G+WWvmYecKylBKEeUGlb6MQuuWmCN5QU3sAM49Xj2dk4f8w0ZbubV6t4CmFny\nDlU5IgCmmng/J+h4L/Py5CMVA47+jscNq6nTt8OMA+Fj/PHUrcydR0gQyhXDy2j1ocPZX69dkTnu\nesa+H2cNBUbkKJDoBZI5qoxVKSIApoJEiDr/eD/Qt5VJ2QKLmZohF6ko8MQbWexl9deAi+/J3V6b\nzI3iDDLwS1I+CNMRTyOFgJ2/v9MHXP044J+TP/eP4WTqaWdAvIKyIAJgKujfTp1//04GZXmac/v6\np9n+xUw9gOaL87fXSSbFajh/4mMWhFJRt4IpIpQre7pogBN6zQLg1GPAkd/m7s9wUh0U2sd8W9mS\nz1UpIgAmm3StXjPGhGzpxFX56N8OHH+QofKv/UthxtzwCap/CulfEMoZ30wGiOWarD1W5bvtdwJd\nG3P3Z7iZZiXaBfS9LPYACxEAk03XRqp84n10zSxkIo/1ABtu5fGa7xRWucuM8wdTM29i4xWEciC4\nGKhZRLVN0iZFxMJbM8ebb8+tDlKGlWsryt+hnXqpypiQAFBKNSql/qSU2mM9Z01hqZQ6qJR6WSn1\nolJq80TuOW3QJr9w8W7ri6nz5+1J89ywyl7Bpfnbp6I0mLmbKQQEoRJwuDhRRzuYL2s0NXOBi76V\nOX8hn3t0lGrS9GJMmPAO4OMAHtNaLwXwmHVuxzqt9QVa6+rIRdy/i6XszCRz9vjn5M/CqTWw7QuM\nDva1AVf/Jf99tAnEupksSyZ/oZJw+BnL4mqwTxTXtAaY+9c87n2eiy476pZTBetpYCSxqIEmLABu\nBJCu4PxjADdNsL/KwEwAiT6u/lPRwoOxIieAo1YR7HM/W1j+nqGjNBI3tVtRlIJQIbgCdGhw+HI7\nTay4A1hwC4/tKocNx+Hl77Nnc9UbhCcqAGZordNJOU4CmGHTTgN4VCm1RSl1W64OlVK3KaU2K6U2\nd3Z2TnB4JcBMcOWfjHCbWWjx9fAx4Mk38thVx8RY+dCm5eFQKxG/QmViuOnOnAxnzxQK8Dew4B2s\nCLbn2/bthvcZ7wViXUDkZPHHPI3I64uolHoUwMwsL31q+InWWiul7EJPL9NaH1NKtQL4k1Jql9Y6\na05XrfU9AO4BgPb29ukTyhrt4oo/2kWjVaKPLpmOAjJ8Pv46vjfNax4trGhLtNNSL82d2NgFoVwx\nHEDd2QyIjPewkHw2vC3AvLewTvbO/wDO/mTufp0BLtZC+7mQqq3OnFl5dwBa66u11udkefwOwCml\n1CwAsJ47bPo4Zj13APgNgDXF+whlQPg4K3oN7AJinTQyBRYzGCvfRB4+PHLyv/yBwit2KQMILMof\nUCYI0xmnVco0GeKix44llnLhyK+B7jy+Ju46wNsMmFG6Z2uzeOOdRkxUBfQAgLQv1q0Afje6gVKq\nRikVTB8DuAZAZeVpDe0FUiHqFpUD8M0ofBIf3Jc5PuezhenxzSRtC8rIn0hOECoBVy1X//E+e7dQ\nVy2w9l4ep21p+UhFuVsPVWcZyYkKgC8BeK1Sag+Aq61zKKXalFIPWm1mAHhKKbUVwHMA/qC1fmiC\n9y0P4r3cmiYGuT11N3ACdwULe3/4OAu8OHzA1U8Ac/KkuE0zdIgF4f1zCosREITpjsuK/PXPyuPp\ns5IqoxMPM5gyH4abQmVwH73pqowC8hHYo7XuBnBVluvHAdxgHe8HUFm5CbTJdMtDBzl5p2JM7KYc\nhfex9dPAiT/y2N1YeNEWbfI+3mYgeNaYhy4I0xZHDV1DE0NcfLmzhh3xd9G/nfaAsz+Ve5fsnw1g\nNhA+CQzsBmqXW1lEq8OpQpaPY8FMcZXQ9ZxVxD3E1bi3iQmsCu4nkZn8AeDczxX+3lgXa/w6awvL\nJyQIlYK3Gag/l8FciSF7b58VH+Hz8T8Cf7oMCB3M37e7lgFnfS/lTytRQYgAGAuxLhqX4t3cNqZi\nQHBRYeUc0/RtAx5Zy+M5N7K0Y8vawt6rNQDFGr+Nq8Y8fEGY9hgea8dsefFkw+EBZqzLnB/7HdOr\n5MLpZ+K5ZIi7i6EjxRtzGSMCIB/JIer4o13A4C4ajFIxup2Np9buxndnjme/sfD3aU0PI29r1WxP\nBeEMlAJqz6JaJ3zYPqfPqq8A1z7H4wP3AS/mSlJgEVhAo7AZB8KWAAgft69OVgGIALAj2snw896X\ngP4dTOcc7WKyNW8z4K7n81hIxTLHDau5nS0EbVI/mYzQ8CsI1Yy3NfMbzBXIpQxg2T/xuPd5qmvz\nkYpxZ5GMAH076GyRrwD9NEaUyHYM7KaxNTEAJPq54nDX02vAcI+9v66NzFgIAOd9Hmi7vvD3xnvp\nXaSc+QPLBKEaMDw0COdbwy64hfmCnvkboGsDUDM/d/vas7gLiBwHDIP30JWbOVQEgNYAdMadMhWn\nkUknMsVYauaP3+C674fAnm+OvNZ6+dj6SAww2tfTZH3pBaHKMVwZD7xcHkFKAcFlVNfuvAs49DNg\nzk3Aoltt2hu0B/jncnfhAe+hzYp0uRYBMHQQiPUy6dTgHkYFKhcNvt5ZVnBXgUFd2Rg++bsbgXM+\nU7jtIBmiDtJdZyXFkqAvQQDAetfuBqD7Of5+7QQAwN9vOv1z+AjwyjfOEADrd3Xgvg2H0BmKoSXg\nwS1r52Pd7AQXX2aC6da9LValssoRBJXzSQpBm9aKH/ynRjuZZCo5yC/S4B6uJqInuQJw+iY2+Y/O\nNHjpT4DWywp/fyrOtNDuZpn8BWE46ZW6w5/x4MnF4r8beR7NZK1Zv6sDd6/fi45QDBpARyiGu9fv\nxfpjtezf4QMG9wK9W3OnopiGVL4ASA5l3MV6t1rJnzQQ6eCkH++ji1jkJCf7mnl8TNTTJhkBtnyI\nxzULgdc+VXi+fm1SDxnroiBqrqzUSYJQNBov5O81cir35Lz071k8psFynx6WNvq+DYcQS47MBRRL\nmrhvwyHG9ygnI/0jpybjE5SUylcB9b5MFUoqYpWEizCYSycZSBI+RK8CZyAz6U90i9fzQqaq14yr\ngFVfLvy9iQFLGDmsuqhj9DQShGrCcHCRNLiHiz3dZP/7bVpD77vHrgK6ngU8rUDDeegMxbI2P33d\nXc/7mAnex+m3jNDjcAYpMypfAKTCQMrFVb4yLDWQJe099YCzyG6ViUGgd0vmfEWeMnXD0SkKKFct\nU0u46ngsCII9rgB/K2ldf65cXIaTQZRHf8PHJT9CS8CDjixCoCXgybzH3UDNQfQUXcMBILiEC0nf\nrPz3LVMqVwUU72PUrhkHot1cWcd7+Y+KdfFYFVn+Pff3wGPrgD3fyVwbywp+6AgFiMPLjKL1K4s7\nPkGoVFxBrsrDxzJ2PjsWvy9z3LcNt6ydD49z5FTocRq4Ze0ol1GluDOPnmRQ5sAOppmIdgL9O4vz\nOaaYyhUAA6/wn2TGgXgXV/+Gm66UtcuA4OLiGlYjJ4GeYSv/pe8HXvOnwt+vU9xiuhqY9EoZFeVt\nIAiTSsMq7pY9DVzc5aL+HODaTUBgCbDrLqxb7Mft65agNeCBAtAa8OD2dUuwbnmW4jOeZqpmXbW0\nCST6eD8zNi1rClSuCshwWnnDDSC4NMtkOgHvntFoE3ji9Znzsz8JzP2rwt8f6+KORSnaK9I+/4Ig\nFIZS1M07g1yhO/25F3hK0bU6tBd47u+w7pIfYt3yiwq7j8Nr9a3pTRTrtOKHUtNu0Ta9RjtWzBR3\nAJP5T3npM8DDw7x0zv7U2CZ/gIEmnmaqpAKLGPXr8BR3nIJQ6fjnWRH7jSPTrtixxHLUGNwD/Plq\nPo8Fdz31/9GTtDXmc0UtQypbAHga6CI2GSSHgBc/CRy36t7ULOC2cu6bxthPmIFnrjp6Ijkl0lcQ\nxoVSQO0KwDfbvmrYcDzNzMY77y10u3767czWOxZcQebn0im6mYePAt2buCOYBlSuCghgAEexA6gG\n9wJP38yVemhYlsCVHxsRNJY1snC0TlFr5hxRbtollDG+DKOCIBBXgL+lVJjG2UKcMJZ+ADj8Cx5v\nfDdwxf+lnr9QDDc1DUMHrURyIdoDmy8ue5VQeY+u3Nj7PU7+gDX5G8DCdwPXbASaMvpD28jCXZno\nQ5hJhpc7A/Qndnhl8heEYqAUq4KZMeroU9Hc7Ue7Wj/xeqDn+bHdM7gY8M4AIscoBGJd7CM5xCzC\nZYoIgELpfQnY+52R1y76FrDs9jMSxeWMLExjRhkZ7LHyi0iOf0EoHg4ff1upGBAuIJ3zukdGnj93\n29jv6QoyNsDfZgWeDnIn0LMJGNg39v6mABEA+TCTwCvfAp59T+Za3Urg2meBpvasb8kbWZgIAUNH\n6e3TcB4QWFzsUQtCdWM4mNrZP5s763yxAZ5G4LJfYoR34EPtjCsYD9qkCip6isehfSPyD5ULIgBy\nceA+4JFLgP0/yFxbcw9w8fdyFoA/HUGY7bpO0W/Y08wvncMLBPLkKBcEYex4mpgrSCna7uxqCKcJ\nLAAu/O+R1568ETjxSNbmee/trqNziG8m7QIDu6g6jvfSQzF8fOxG5yIjAiAbiUHguQ8Au0d9GYJL\ngcbVeQvC5IwsTEX45fDPkTQPgjDZKIP5f/yzaaTNR8ulNAIHl2aunRxDQGcaT6Pl2m3NAzrBSP/Q\nAVYa630eiJ4A4v1Az4uFua1OApXtBTRWho4AnU8Cu/7rzNcu+VHBqpq0t88IL6BL5mHd3DgQiwAN\nF8qqXxCmCl+rlSeoANdQgCv2i74D/Pkqnnc9Ry+f8VQCTBNcwkk+2sFZV8cBw8fnpObCsASxP9Ut\nAMwksO97wPybWa5xYNfI1+e8iS5iZnxsbmGgEBjh9pmMcBVgmtMyaZQgTGucfqt6WD9VMDXzc9f6\ncNcBr7of2PVVpo1/5FJg5jXA+XeO37XTcFnp6WM0UjtNKwOAE+h7me6rsV4guGjKnEKqVwAc+Q3r\n/h75JYXAaC79XxqRisHAHiaqaljFJG9S3EUQphbDS5VMtIOu16khPuciuARYdRfwqFXC9eQjwKJ3\nj39eUAZQt5yLQTNG99Sa+TQURzsAKBqOXUF6Ek0B1SUAEgNWEqeTwPYvnPn6rOuBlXcU1y3TjFsG\n3yYguKA4fQqCMDYMBwOzTj3BFA7xnvwCAODO4bJfMlDs8M+BZ97B69dsHH+dcKcPgC9z7pvJmKBo\nJ4VE3zYKhcZV4+t/LEOZ9DtMMb994Ri+8vBuNERfxrxajbdcsoyqmOMPAS/9C9DYzgl+NK95lF+M\nYpIcohtZ3dl09xQEoXQYLq6uvTOAyAmuwA13fpVOYAEXhg3nAVs/xWsvfxY4P8sicry46+l84mtj\ncrkpyixaUQLgty8cwyd+/TIiiRTqvcCM1HbM3vU1HOh7NRb2/R826tmcecPyDwOtV/KLUazJPzHI\nid9wUdfoa2NAiiAIpafhAurcB15h3h7DA9TMLey9rVdkjk88zMc5nwVmvRaAmpgR11Wb8Qp0+Cdm\ncB4DFSUAvvLwbkQSKayt2Yob6p7CLc1/5At9wyJwa+YzUVPjamDBO4s/iGgHjUvax2LudWdLWUdB\nKBfSk3TtUqA/UbhnEEDb3UXf4cR/9De8tu1zfPjnAJf/tvjjnWQqSgAc74sAANbVbs5M/mlWfYVB\nIZPpe681t26OGsBdC9SfJ77+glCO+OdYFfgG+Jst1LOnqZ3zyIJ3Ak+9OXM9fHRyxjnJTCgQTCn1\nFqXUdqWUqZTKnheB7a5TSu1WSu1VSn18IvfMRVs9dftfOfmu09fu7boBn+78F2DGusmfjBP9nPjd\nDYB/PtVKZZ4NUBCqEmVwFxBYxHrhqWjhenelaBeY99ZJHeJUMNHZaRuAvwLwpF0DpZQDwDcBXA9g\nJYC3K6UmpdjtHdcug8/lQEK78Me+tTC1wmNDr8ZrLrp0Mm6XIb3yT3sWNK6WQC9BKHe8rVaahiF6\nBo51Fb/yo0D7NzPnT94E7P4GcPQBYM//FHesk8SEVEBa650AoHIFVABrAOzVWu+32t4P4EYAOyZy\n72zctGo2ANoCvtnxNvw++la8+4pl2Wt7FoNkyEoWpfhw1wPOWinqIgjTBe9MponQGhg6kHEVL5Tm\ni+lB+OerKUAO/Djz2uL3jt9VdIqYitHNBnBk2PlRABdP1s1uWjWbgqCnnhP0ZOTYT0asqL4I1T3p\njZQrCDReUPz7CYIwORhOTuLRLrpfJgZZVzj3onYk7nrgqj8Dj71m5PXoKSZ/nKyqhEUgrwBQSj0K\nIFsehE9prX9X7AEppW4DcBsAzJtXhn+48FErrUOS8QS+WQAUdYpuKeQuCNMSw8GJXCeBWDcXjs4s\n8UJ2uGqB1/wJ6HgC2HYnrz15I58v/h7dT8uQvAJAa331BO9xDMBwR9s51jW7+90D4B4AaG9vz5PE\nuwSYSWtXoRleHlzKItSGfXpoQRDKHHcDkz0OHeQuINxLI/FY+5hzE+MF/vzazPVn38fnV/2MlcPK\niKlwUdkEYKlSaqFSyg3gZgAPTMF9i4uZYE5xZ4B1R70zWHTeVSuTvyBUAv42/p6dAapzB/cylctY\ncTcAlz/AILHmYQ4oT7+NBeMBzifbvzj+gjNFYqJuoG9SSh0FsBbAH5RSD1vX25RSDwKA1joJ4HYA\nDwPYCeDnWuvtExv2FKNNIHTQKtoeAOrPZ0qJpotKksJVEIRJwjuDv3FvK+CfRw+h8eBvA+a8AWj/\nOrDyY5nrmz4A7Pk20PsicOTXwI4vF2fc40TpfKXSSkh7e7vevHlz/obZ6Hl+4kZgbTKdgzPAMo5K\ncYXQPGk2bEEQSo2Z4HPkBFNBBxYWp9+HbEKl1v4YqF2ZMTwnQlQrN5w7rtsopbZorW3jsoYjUUrZ\nSPv1hw5wCxg5Bjg99A7wTU2aVkEQSoTh4kOn+JsfOlSc5GyL35f9+oZbgSdeT9vDFFPeTqqlwEyw\nbqezBnDV06dfOenh42tjqTdBECofdz1TRsQ6gNAhrtDzFZLJxdL3A0tuA7qeBbqeZr2B3q3Asd/T\nZfSxdfQWWvZhwFVX3M9igwiANGaSQSDpQBBlUAgYTmbz9DTJ5C8I1YS7gY/EfKBrIwANhI8weni8\n2TqVAbSs5QOg15C3Fdj3fZ73vghsvBVY8g/Amm/a91MkqlsAJIeo7jHjDAJxN3KSdwY46bvruRV0\n+Mcv9QVBmN64AnT2cPj4CB3kTqBYDiBLPwC0rgNe+AgQPclrdZOSLecMqlcAJEJArAuACcABBJcB\n0EDtcv7DBUEQ0nhncjegU0BygCqbYkb41i0Hrvg98OJHWUK2aWocTapHAGiTK/1EiHr+RD+t+6kI\noG/ub5IAAAb0SURBVMGgD0ndLAhCNtJBYYlBwNUIoJ8F3YtZRVAppq1PhKbMvbx6vIBCh1h3UzmY\nu83TyDQO/jmsvVlIfVBBEKobVxBoXsP5wkwxjfQ0pnJ3AMrBVX/4KCv5KANwW+lfDSeld7H8ewVB\nqB6UwSDQ0H6gbysXkTo5LReRlSsA3I3AwG5a2OP9jPAznED92Xx9ioouC4JQgTjcrCUc6+YiUzkB\nn5OLTYBqHKe/7AtCVa4ASPvvBxYDQ/uBhvPp0ZOmzP8xgiCUOc4aoOlCoM8DpGIsKuPwAMkwAA14\nmsdsI1i/qwO/3LgLe/tdCPk6cce1y07XOZkMKlcAGB7+g9z1gDlbPHsEQSg+Di/QsIqeQT1R7ggc\nXtDQODbW7+rA3ev3wmHGoOHCsb4IPvHrlwFg0oRA5S6DnX6g7hwKgeCSUo9GEIRKxXDQRbThAsYH\nGB7AXcfg0jFw34ZDiCVHqqYjiRS+8vDuYo52BJUrAJQB1MwWVY8gCFODp4mJIh1uBo+aMSB8vGBP\noc5QLOv1432RYo5yBDI7CoIgFBOHnxHDykENRLyP15MRZh6woSWQ3fe/rX4MlcnGiAgAQRCEYtJw\nAV3MPc1A7TKmpQ8dpHE40Wf7tlvWzofHOXJK9rkcuOPaZZM21Mo1AguCIJSCdBRv88VU/zS/yrIJ\nG0DnU0DkFBBYQIGQDAM1cwAA65a3AgB+uXEX+vuB2fU+8QISBEGYtji8pyd4pGKAbzYQ7+KOwOGl\nmijawXglUAisW+yfUEGYsSAqIEEQhKnA4QHqVwKeGZzw3fWZBHPh4yUJThUBIAiCMFW4G4CWS2go\ndjcxD5nhYaLK0P4pH46ogARBEKYaXxvgqmEGYmeQXkOpCBA+xhimKUIEgCAIwlQTHJaIsm4FU0H3\nvgxAMaWEv4i1BnIgAkAQBKGUuK36v95WIN4D6DjGk0piPIgAEARBKAeCi4HkTGBgF1NKTAEiAARB\nEMoBZbDgTNNFU3ZL8QISBEGoUkQACIIgVCkiAARBEKoUEQCCIAhViggAQRCEKkUEgCAIQpUiAkAQ\nBKFKEQEgCIJQpSido0RZqVFKdQI4NM63NwPoKuJwSkmlfJZK+RyAfJZypFI+BzCxzzJfa91SSMOy\nFgATQSm1WWvdXupxFINK+SyV8jkA+SzlSKV8DmDqPouogARBEKoUEQCCIAhVSiULgHtKPYAiUimf\npVI+ByCfpRyplM8BTNFnqVgbgCAIgpCbSt4BCIIgCDmoaAGglPq8UuolpdSLSqlHlFJtpR7TeFFK\nfUUptcv6PL9RStWXekzjQSn1FqXUdqWUqZSadh4bSqnrlFK7lVJ7lVIfL/V4xotS6gdKqQ6l1LZS\nj2WiKKXmKqXWK6V2WN+tD5Z6TONBKeVVSj2nlNpqfY7PTfo9K1kFpJSq1VoPWMf/BGCl1vr9JR7W\nuFBKXQPgz1rrpFLqywCgtf5YiYc1ZpRSKwCYAP4HwEe01ptLPKSCUUo5ALwC4LUAjgLYBODtWusd\nJR3YOFBKXQ4gBOBerfU5pR7PRFBKzQIwS2v9vFIqCGALgJum2/9FKaUA1GitQ0opF4CnAHxQa71x\nsu5Z0TuA9ORvUQNg2ko7rfUjWuukdboRwJxSjme8aK13aq13l3oc42QNgL1a6/1a6ziA+wHcWOIx\njQut9ZMAeko9jmKgtT6htX7eOh4EsBPA7NKOauxoErJOXdZjUuesihYAAKCU+oJS6giAdwL4TKnH\nUyTeA+CPpR5EFTIbwJFh50cxDSeaSkYptQDAKgDPlnYk40Mp5VBKvQigA8CftNaT+jmmvQBQSj2q\nlNqW5XEjAGitP6W1ngvgJwBuL+1oc5Pvs1htPgUgCX6esqSQzyEIxUYpFQDwKwAfGrX7nzZorVNa\n6wvAHf4apdSkquemfVF4rfXVBTb9CYAHAXx2EoczIfJ9FqXUuwG8HsBVuoyNN2P4n0w3jgGYO+x8\njnVNKDGWzvxXAH6itf51qcczUbTWfUqp9QCuAzBphvppvwPIhVJq6bDTGwHsKtVYJopS6joAHwXw\nRq11uNTjqVI2AViqlFqolHIDuBnAAyUeU9VjGU+/D2Cn1vqrpR7PeFFKtaS9+5RSPtDZYFLnrEr3\nAvoVgGWg18khAO/XWk/LFZtSai8AD4Bu69LG6ejRpJR6E4BvAGgB0AfgRa31taUdVeEopW4A8DUA\nDgA/0Fp/ocRDGhdKqZ8CuBLMOnkKwGe11t8v6aDGiVLqMgB/AfAy+FsHgE9qrR8s3ajGjlLqPAA/\nBr9bBoCfa63/bVLvWckCQBAEQbCnolVAgiAIgj0iAARBEKoUEQCCIAhViggAQRCEKkUEgCAIQpUi\nAkAQBKFKEQEgCIJQpYgAEARBqFL+H5EQSZVlWEuSAAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x10abc6588>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "x = np.linspace(-3, 3, 1000)[:, None]\n",
    "plt.scatter(x_train, y_train)\n",
    "y = [model(x) for _ in range(100)]\n",
    "y_mean = np.mean(y, axis=0)\n",
    "y_std = np.std(y, axis=0)\n",
    "plt.plot(x, y_mean, c=\"orange\")\n",
    "plt.fill_between(x.ravel(), (y_mean - y_std).ravel(), (y_mean + y_std).ravel(), color=\"orange\", alpha=0.2)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
